﻿// Copyright (c) 2017 GlassGrass

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UniRx;

namespace GlassGrass.Unity.GuiFramework
	{
	/// <summary> Click and double click event observable button. </summary>
	public class Button : GuiElement
		{
		#region events

		// internal click observable for dispatch click or double click
		private readonly Subject<bool> _clickInternal = new Subject<bool>();

		/// <summary> Be fired when this was clicked. </summary>
		public IObservable<EventArgs> Click => _click;
		private readonly Subject<EventArgs> _click = new Subject<EventArgs>();

		/// <summary> Be fired when this was double clicked. </summary>
		public IObservable<EventArgs> DoubleClick => _doubleClick;
		private readonly Subject<EventArgs> _doubleClick = new Subject<EventArgs>();

		#endregion



		/// <summary> Create Button instance. </summary>
		/// <param name="config"> [Non-Nullable] </param>
		/// <exception cref="System.ArgumentNullException"></exception>
		public Button(GuiConfig config)
			:base(config)
			{
			_clickInternal
				.Buffer(_clickInternal.Throttle(Config.DoubleClickInterval))
				.Where(clicks => clicks.Count == 1)
				.Select(_ => EventArgs.Empty)
				.Subscribe(_click)
				;
			_clickInternal
				.Buffer(_clickInternal.Throttle(Config.DoubleClickInterval))
				.Where(clicks => clicks.Count >= 2)
				.Select(_ => EventArgs.Empty)
				.Subscribe(_doubleClick)
				;
			}



		#region override methods

		/// <summary> Define what to choose style for this from skin. </summary>
		/// <param name="skin"></param>
		/// <returns></returns>
		protected override GUIStyle ChooseStyle(GUISkin skin)
			=> skin?.button;



		/// <summary> Define how to layout manually itself on rendering frame. </summary>
		/// <param name="parentSkin"></param>
		public override void LayoutManual(GUISkin parentSkin)
			{
			if (GUI.Button(Rect, Content, SelectValidStyle(parentSkin)))
				ClickInternal();
			}



		/// <summary> Define how to layout automatically itself on rendering frame.  </summary>
		/// <param name="parentSkin"></param>
		public override void LayoutAuto(GUISkin parentSkin)
			{
			if ( GUILayout.Button( Content, SelectValidStyle( parentSkin ), LayoutOptions ) )
				ClickInternal();
			}

		#endregion



		// Send click signal to internal subject.
		private void ClickInternal()
			{
			_clickInternal.OnNext(true);
			}

		}
	}
